
 
if(!window.XO)
    XO = {};

(function(X, $){

var undefined,
    doc  = document;
   
X.collection = {};
X.model = {};
X.view = {};
X.tmpl = {};
X.cache = {};

var util = X.util = {
    create : function(){
          var clazz = (function() {
            this.init.apply(this, arguments);
          });

          if (arguments.length === 0)
            return clazz;

          var absObj, base, type, ags = $.makeArray( arguments );

          if (typeof ags[0] === 'string') {
            type = ags[0];
            base = ags[1];
            ags.shift();
          } else base = ags[0];

          ags.shift();

          if (base)
            base = base.prototype;
          
          if (base) {
            function Bridge(){};
            Bridge.prototype = base;
            clazz.prototype = absObj = new Bridge();
          }

          if (type) {
            absObj.type = type;
            util.ns(type, clazz);
          }
          
          for(var i=0,len=ags.length;i<len;i++)
            absObj = $.extend(absObj, typeof ags[i] === 'function' ? ags[i]( base ):ags[i]);
          
          absObj.constructor = clazz;
          return clazz;
    },

    domUp : function(el, selector, end){
      end = end || doc.body;
      var isStr = typeof selector === 'string';
      while(el){
          if(isStr){
              if($(el).is(selector))
                  return el; 
          }else if(selector(el)){
              return el;
          }
          el = el.parentNode;
          if(el === end)
              return null;
      }
      return el;        
    },

    parseKnV : function(strRel){
      var map = {}, kv, kvs = this.split(strRel||'', ',');
      try {
          for( var i=0,len=kvs.length;i<len;i++){
              // if not contains ':'
              // set k = true
              if(kvs[i].indexOf(':') === -1){
                  map[kvs[i]] = true;
              }else {
                  // split : to k and v
                  kv = util.split(kvs[i], ':');
                  // escape value
                  map[kv[0]] = kv[1];
              }
          }
      }catch(e) { 
          if(__debug) console.trace();
          throw 'Syntax Error:wrong rel format' + strRel; 
      }

      return map;
    },


    split : function(str, splitChar, escChar){
        var c, arr = [], tmp = [];
        if(!escChar)
            escChar = '\\';
    
        for(var i=0,len=str.length;i<len;i++){
            c = str.charAt(i);
            if(c === splitChar){
                arr.push(tmp.join(''));
                tmp.length = 0;
                continue;
            }
            else if(c === escChar && str.charAt(i+1) === splitChar){
                c = splitChar;
                i++;
            }
            tmp[tmp.length] = c;
        }
        if(tmp.length)
            arr.push(tmp.join(''));
        return arr;
    },

    //safe insert text to HTML document
    encodeToHTML : function(html){
        return html.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
    }

    //set price to decimal
}


$.extend(X, {
  
  getCfg : function(key){
    return X.cfg && X.cfg[key]; 
  },


  getUserCfg : function() {
    return X.getCfg('userCfg');
  }
  
})





$.extend($.Event.prototype, {

    q : null,

    init : function(){

        if(this.q) return true;
        this.q = this.collectRels(this.target, $('body'))

    },

    jq : function(name){

        this.init();
        if(!name)
            return $(this.currentTarget)
        else
            return $(this.getRel(name).src)

    },

    get : function(name){

        this.init();
        if(!name) return this.q && this.q[0].data
        var r = this.getRel(name);
        return r && r.data && r.data[name];

    },

    //s {Number} 0:unlock, 1:lock
    lock : function(s){
        
    },

    // private
    getRel : function(name){
        var set = this.q || [];
        if(set.length){
            for(var i = 0; i < set.length; i++){
                if(name in set[i].data)
                return set[i];
            }
        }
        return false;

    },

    parseRel : function(rel){
        if(typeof rel === 'string')
            return util.parseKnV(rel);
        return util.parseKnV($(rel).attr('rel'));
    },

    collectRels : function(trigSource, stopEl, cache){
        var 
            rels, 
            rel, 
            self = this;
        
        if(cache===undefined)
            cache = true;
        
        util.domUp(trigSource, function(el){
            var jq = $(el);
            
            if(cache){
                rel = jq.data('xwb_rel');
                if(!rel){
                    rel = jq.attr('rel');
                    if(rel){
                        rel = {src:el, data:self.parseRel(rel)};
                        jq.data('xwb_rel', rel);
                    }
                }
            }else {
                rel = jq.attr('rel');
                if(rel)
                    rel = {src:el, data:self.parseRel(rel)};
            }
        
            if(rel){
                if(!rels)
                    rels = [];
                rels[rels.length] = rel;
            }
        
        } , stopEl);
        
        return rels;
    }

})

//padding backbone-form.js_lib for subForm template
Backbone.Form.editors.Object.prototype.render = function(){
    this.form = new Backbone.Form({
        schema: this.schema.subSchema,
        data: this.value,
        idPrefix: this.id + '_',
        fieldTemplate: this.schema.subFieldTemplate || 'nestedField',
        fieldsetTemplate : this.schema.subFieldsetTemplate,
        template : this.schema.subTemplate
    });
    this.$el.html(this.form.render().el);

    return this;
}

Backbone.emulateJSON = true;

})(XO, $);